#include <stdio.h>
#include "sdkconfig.h"
#include "esp_camera.h"
#include "pca9557.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

/**
 * W (6525) cam_hal: Failed to get frame: timeout
W (6525) main: Camera frame capture failed
W (10575) cam_hal: Failed to get frame: timeout
W (10575) main: Camera frame capture failed
 * 
 */
#define XCLK_FREQ_HZ 20000000
#define dvp_pwdn(data) pca9557_set(DVP_PWDN, data)
#define TAG "CAMERA"
// 摄像头硬件初始化
void bsp_camera_init(void)
{
    dvp_pwdn(0); // 打开摄像头
    vTaskDelay(pdMS_TO_TICKS(200)); // 等待摄像头电源稳定

    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_1;  // LEDC通道选择  用于生成XCLK时钟 但是S3不用
    config.ledc_timer = LEDC_TIMER_1; // LEDC timer选择  用于生成XCLK时钟 但是S3不用
    config.pin_d0 = CONFIG_DVP_D0_PIN;
    config.pin_d1 = CONFIG_DVP_D1_PIN;
    config.pin_d2 = CONFIG_DVP_D2_PIN;
    config.pin_d3 = CONFIG_DVP_D3_PIN;
    config.pin_d4 = CONFIG_DVP_D4_PIN;
    config.pin_d5 = CONFIG_DVP_D5_PIN;
    config.pin_d6 = CONFIG_DVP_D6_PIN;
    config.pin_d7 = CONFIG_DVP_D7_PIN;
    config.pin_xclk = CONFIG_DVP_XCLK_PIN;
    config.pin_pclk = CONFIG_DVP_PCLK_PIN;
    config.pin_vsync = CONFIG_DVP_VSYNC_PIN;
    config.pin_href = CONFIG_DVP_HREF_PIN;
    config.pin_sccb_sda = -1;   // 这里写-1 表示使用已经初始化的I2C接口
    config.pin_sccb_scl = 2;
    config.sccb_i2c_port = 0;
    config.pin_pwdn = -1;
    config.pin_reset = -1;
    config.xclk_freq_hz = XCLK_FREQ_HZ;
    config.pixel_format = PIXFORMAT_RGB565;
    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 12;
    config.fb_count = 2;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.grab_mode = CAMERA_GRAB_LATEST;

    // camera init
    esp_err_t err = esp_camera_init(&config); // 配置上面定义的参数
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Camera init failed with error 0x%x", err);
        return;
    }

    sensor_t *s = esp_camera_sensor_get(); // 获取摄像头型号

    if (s->id.PID == GC0308_PID) {
        ESP_LOGI(TAG, "Configuring GC0308 sensor");
        s->set_hmirror(s, 1);  // 这里控制摄像头镜像 写1镜像 写0不镜像
        // GC0308特定配置
    }
}
